/**
 * 配置
 * */
package org.zmhhxl.samples3.resource.gateway.configure.client;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;

import java.util.*;

/**
 * 也可配置于独立客户端,属于非流式客户端
 * 客户端-服务器配置类
 * 用于管理客户端和服务器之间的配置信息
 * 2024-4-10
 */
//@Configuration
public class ClientServerConfig {
   /**
    * 创建并配置一个GrantedAuthoritiesMapper的bean，用于映射用户的权限。
    *
    * 解析用户权限信息（当在浏览器中直接访问接口，框架自动调用OIDC流程登录时会用到该配置）
    *
    * @return 返回一个GrantedAuthoritiesMapper，它接受一个权限集合，映射后返回一个新的权限集合。
    */
   @Bean
   public GrantedAuthoritiesMapper userAuthoritiesMapper() {
      return (authorities) -> {
         Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

         authorities.forEach(grantedAuthority -> {
            /**
             * 如果权限是OAuth2UserAuthority类型的实例，
             * 则从该权限的属性中获取一个名为"authorities"的属性值，
             * 将其转换为一个字符串集合，并将每个字符串转换为SimpleGrantedAuthority
             * 类型的实例
             * */
            if (grantedAuthority instanceof OAuth2UserAuthority) {
               OAuth2UserAuthority oAuth2UserAuthority = (OAuth2UserAuthority) grantedAuthority;

               Object userAuthorities = oAuth2UserAuthority.getAttributes().get("authorities");
               if (userAuthorities instanceof Collection<?>) {
                  // 使用 Java 8 流处理并合并操作以优化性能和可读性
                  ((Collection<?>) userAuthorities).stream()
                        .filter(Objects::nonNull) // 过滤null值
                        .filter(a -> a instanceof String)
                        .map(String::valueOf)
                        .map(SimpleGrantedAuthority::new)
                        .forEach(mappedAuthorities::add);
               }
            }else if (OidcUserAuthority.class.isInstance(grantedAuthority)) {
               OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)grantedAuthority;

               OidcIdToken idToken = oidcUserAuthority.getIdToken();
               OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();

               // Map the claims found in idToken and/or userInfo
               // to one or more GrantedAuthority's and add it to mappedAuthorities
               //Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();

               // Map the attributes found in userAttributes
               // to one or more GrantedAuthority's and add it to mappedAuthorities

            }

         });
         return mappedAuthorities;
      };
   }
}
